package com.zxl.live.tools.image;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.text.TextUtils;
import android.util.LruCache;

import com.zxl.live.tools.common.ApplicationHelper;
import com.zxl.live.tools.tools.FileUtil;
import com.zxl.live.tools.tools.HttpUtils;
import com.zxl.live.tools.tools.LogUtils;

import java.io.IOException;
import java.lang.ref.SoftReference;
import java.util.HashMap;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;

/**
 * 
 * 
 * 类名称：ImageLoaderManager
 * 类描述：图片加载器
 * 创建人：makai
 * 修改人：makai
 * 修改时间：2014年7月7日 下午3:32:56
 * 修改备注：
 * @version 1.0.0
 *
 */
public class ImageLoaderManager {

	private static ImageLoaderManager sInstance;

	private LruCache<String, Bitmap> mLruCache;
	
	private HashMap<String, SoftReference<Bitmap>> mHashMap;

	private ImageExecutorService mExecutors = new ImageExecutorService(3);
	
	private static final int DEFAULT_SIZE = 5 * 1024 * 1024;

	private ImageLoaderManager(int size) {
		mHashMap = new HashMap<String, SoftReference<Bitmap>>();
		size = Math.max(size, DEFAULT_SIZE);
		LogUtils.d("ImageLoaderManager size : " + size);
		mLruCache = new LruCache<String, Bitmap>(size) {
			@Override
			protected void entryRemoved(boolean evicted, String key, Bitmap oldValue, Bitmap newValue) {
				if (evicted) {
					mHashMap.put(key, new SoftReference<Bitmap>(oldValue));
				}
			}
			
			@Override
			protected int sizeOf(String key, Bitmap value) {
				return value.getRowBytes() * value.getHeight();
			}
		};
	}

    /**
     * 线程
     * @param runnable
     */
	public void execThread(ImageExecutorService.ImageRunnable runnable) {
		mExecutors.execute(runnable);
	}

	public static ImageLoaderManager getInstance() {
		if (null == sInstance) {
			sInstance = new ImageLoaderManager(-1);
		}
		return sInstance;
	}

	public static void init(int size) {
		if (sInstance == null) {
			sInstance = new ImageLoaderManager(size);
		}
	}

	public Bitmap loadBitmapFromMemory(String url) {
		Bitmap bitmap = null;
		if (!TextUtils.isEmpty(url)) {
			bitmap = mLruCache.get(getKey(url));
			if (null == bitmap || bitmap.isRecycled()) {
				SoftReference<Bitmap> softReference = mHashMap.get(getKey(url));
				if (null != softReference) {
					bitmap = softReference.get();
					if (null == bitmap || bitmap.isRecycled()) {
						bitmap = null;
					}
				}
			}
		}
		return bitmap;
	}
	
	public void saveBitmapToMemory(String url, Bitmap bitmap) {
		if (null != bitmap && !bitmap.isRecycled() && !TextUtils.isEmpty(url)) {
			mLruCache.put(getKey(url), bitmap);
		}
	}
	
	public Bitmap loadBitmapFromSdcard(String url, String path, boolean isSaveToCache) throws OutOfMemoryError {
		Bitmap bitmap = null;
		try {
			bitmap = BitmapFactory.decodeFile(path);
			if (isSaveToCache) {
				saveBitmapToMemory(url, bitmap);
			}
		} catch (OutOfMemoryError e) {
            throw e;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return bitmap;
	}
	
	public void saveBitmapToSdcard(String url, String path, Bitmap bitmap, byte[] bs, boolean isSaveToCache) {
		if (null != bitmap) {
			boolean isSuccessed = false;
			byte[] ninePatchChunk = bitmap.getNinePatchChunk();
			if (null != ninePatchChunk && ninePatchChunk.length > 0) {
				isSuccessed = FileUtil.saveByteToSDFile(bs, path);
			} else {
				isSuccessed = FileUtil.saveBitmapToSDFile(bitmap, path, CompressFormat.PNG);
			}
			if (!isSuccessed) {
				FileUtil.deleteFile(path);
			}
			if (isSaveToCache) {
				saveBitmapToMemory(url, bitmap);
			}
		}
	}

	public void loadBitmapFromNet(Context context, final String url, final String path, final boolean isSaveToCache, final OnImageLoaderListener loaderListener, final OnImageHandlerListener handlerListener) {
		HttpUtils.doGet(url, new Callback() {
			@Override
			public void onFailure(Call call, IOException e) {
				ApplicationHelper.postRunInUiThread(new LoadImageRunable(url, null, loaderListener));
			}

			@Override
			public void onResponse(Call call, Response response) throws IOException {
				try {
					byte[] bs  = response.body().bytes();
					Bitmap bitmap = BitmapFactory.decodeByteArray(bs, 0, bs.length);
					if (null != bitmap && null != handlerListener) {
						bitmap = handlerListener.onImageHandle(bitmap);
					}
					saveBitmapToSdcard(url, path, bitmap, bs, isSaveToCache);
					ApplicationHelper.postRunInUiThread(new LoadImageRunable(url, bitmap, loaderListener));
				} catch (Error e) {
					e.printStackTrace();
				}
			}
		});
	}
	
	/**
	 * 设置图片
	 * loadImageBitmap(这里用一句话描述这个方法的作用)
	 * (这里描述这个方法适用条件 – 可选)
	 * @param context
	 * @param url										下载地址
	 * @param path									保存地址
	 * @param isSaveToCache						是否保存到缓存
	 * @param isOnlyLoadMemory					是否仅加载内存中的数据
	 * @param loaderListener						加载监听器
	 * @param handlerListener						图片处理器
	 * @return 
	 *Bitmap
	 * @exception 
	 * @since  1.0.0
	 */
	public Bitmap loadImageBitmap(final Context context, final String url, final String path, final boolean isSaveToCache, boolean isOnlyLoadMemory,
								  final OnImageLoaderListener loaderListener, final OnImageHandlerListener handlerListener) {
		Bitmap bitmap = loadBitmapFromMemory(url);
		if (null == bitmap && !isOnlyLoadMemory) {
			execThread(new ImageExecutorService.ImageRunnable(url) {
				@Override
				public void run() {
					Bitmap bitmap = null;
					try {
						bitmap = loadBitmapFromSdcard(url, path, isSaveToCache);
						if (null == bitmap) {
							loadBitmapFromNet(context, url.trim(), path, isSaveToCache, loaderListener, handlerListener);
						} else {
							ApplicationHelper.postRunInUiThread(new LoadImageRunable(url, bitmap, loaderListener));
						}
					} catch (OutOfMemoryError e) {
						ApplicationHelper.postRunInUiThread(new LoadImageRunable(url, null, loaderListener));
						e.printStackTrace();
					}
				}
			});
		}
		return bitmap;
	}

    /**
     * 加载图片
     * @param path
     * @return
     */
    public Bitmap loadImageBitmap(String url, String path) {
        return loadImageBitmap(url, path, null);
    }

    /**
     * 获取图片
     * @param path
     * @param onLoadImageListener 自动以加载器
     * @return
     */
    public Bitmap loadImageBitmap(String url, String path, OnLoadImageListener onLoadImageListener) {
        Bitmap bitmap = loadBitmapFromMemory(url);
        if (null == bitmap) {
            if (null != onLoadImageListener) {
				try {
					bitmap = onLoadImageListener.handle(path);
				} catch (Throwable e) {
					e.printStackTrace();
				}
                saveBitmapToMemory(url, bitmap);
            } else {
                bitmap = loadBitmapFromSdcard(url, path, true);
            }
        }
        return bitmap;
    }


    /**
	 * 加载图片（带有异步线程缓存）
	 * @param path
	 * @param loaderListener			加载完成回调
	 * @param isOnlyLoadMemory			是否仅加载内存数据
	 * @param onLoadImageListener		自定义加载器，为null表示使用内部集成的加载方式
	 * @return
	 */
	public Bitmap loadImageBitmap(final String url, final String path, boolean isOnlyLoadMemory, final OnImageLoaderListener loaderListener, final OnLoadImageListener onLoadImageListener) {
		Bitmap bitmap = loadBitmapFromMemory(url);
		if (null == bitmap && !isOnlyLoadMemory) {
			execThread(new ImageExecutorService.ImageRunnable(url) {
				@Override
				public void run() {
					Bitmap bitmap = null;
					if (null != onLoadImageListener) {
						try {
							bitmap = onLoadImageListener.handle(path);
							saveBitmapToMemory(url, bitmap);
						} catch (Throwable e) {
							e.printStackTrace();
						}
					} else {
						bitmap = loadBitmapFromSdcard(url, path, true);
					}
					if (null != bitmap) {
						ApplicationHelper.postRunInUiThread(new LoadImageRunable(url, bitmap, loaderListener));
					}
				}
			});
		}
		return bitmap;
	}

	private String getKey(String url) {
		return String.valueOf(url.hashCode());
	}

    /**
     * 自定义图片加载器
     */
	public interface OnLoadImageListener {

        /**
         * 图片加载处理
         * @param path
         * @return
         */
		Bitmap handle(String path);

	}

	/**
	 * 
	 * 
	 * 类名称：OnImageLoaderListener
	 * 类描述：图片加载监听器
	 * 创建人：makai
	 * 修改人：makai
	 * 修改时间：2014年7月7日 下午3:34:42
	 * 修改备注：
	 * @version 1.0.0
	 *
	 */
	public interface OnImageLoaderListener {
		
		void onLoadFinish(Bitmap bitmap, String url);
		
	}
	
	/**
	 * 
	 * 
	 * 类名称：OnImageHandlerListener
	 * 类描述：图片处理监听器
	 * 创建人：makai
	 * 修改人：makai
	 * 修改时间：2014年7月7日 下午3:34:58
	 * 修改备注：
	 * @version 1.0.0
	 *
	 */
	public interface OnImageHandlerListener {
		
		Bitmap onImageHandle(Bitmap bitmap);
		
	}
	
	/**
	 * 
	 * 
	 * 类名称：LoadImageRunable
	 * 类描述：图片处理
	 * 创建人：makai
	 * 修改人：makai
	 * 修改时间：2014年7月7日 下午3:35:10
	 * 修改备注：
	 * @version 1.0.0
	 *
	 */
	public static class LoadImageRunable implements Runnable {
		
		private String mUrl;
		
		private Bitmap mBitmap;
		
		private OnImageLoaderListener mLoaderListener;
		
		public LoadImageRunable(String url, Bitmap bitmap, OnImageLoaderListener loaderListener) {
			this.mUrl = url;
			this.mBitmap = bitmap;
			this.mLoaderListener = loaderListener;
		}

		@Override
		public void run() {
			if (null != mLoaderListener) {
				mLoaderListener.onLoadFinish(mBitmap, mUrl);
			}
		}
	}
	
}
